/*编者: 胡小端 
 * AttachItem  将属性赋值给元素, 参数: 元素ID, 库名, 组名, 属性显示名, 属性类型, 属性值
 * getElePropertyValue  从元素中读取某属性显示名的属性值(返回string), 参数: 元素ID, 库名, 组名, 属性显示名 
 * GetProperties 获取某元素的所有属性信息 参数: 元素ID的string格式  注: 属性不缺,但条目与属性窗口不一致,自定义属性完全吻合
 * 调用举例:
 *         long tem = 7736;
            ElementId tempID = new ElementId(ref tem);
            DPoint3d pt = new DPoint3d(1, 2,0);
            ElementProperty.AttachItem(tempID,"hxdtest", "test","源点",TypeKind.Point,pt);
            ElementProperty.AttachItem(tempID, "hxdtest", "test", "姓名", TypeKind.String, "呼呼呼");
            System.Windows.Forms.MessageBox.Show(ElementProperty.getElePropertyValue(tempID, "hxdtest", "test", "源点"));
            ElementProperty.GetProperties("7736");
*/
using Bentley.CifNET.GeometryModel.SDK.Edit;
using Bentley.DgnPlatformNET;
using Bentley.DgnPlatformNET.DgnEC;
using Bentley.DgnPlatformNET.Elements;
using Bentley.ECObjects.Instance;
using Bentley.ECObjects.Schema;
using Bentley.ECObjects.UI;
using Bentley.GeometryNET;

using Bentley.MstnPlatformNET;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using static Bentley.DgnPlatformNET.CustomProperty;
using BIM = Bentley.Interop.MicroStationDGN;
using BMI = Bentley.MstnPlatformNET.InteropServices;

namespace CheccCoverplateCulvertAssemble.Tools
{
    public class ElementProperty
    {
        //DbID=20202
        //写入ID最大为65535
        public static void dataToAppBlock(int DbID,string projectName)
        {
            BIM.Application myApp = BMI.Utilities.ComApp;
            BIM.ApplicationElement Ae;
            BIM.DataBlock DB;
 
            DB = (BIM.DataBlock)myApp.CreateObjectInMicroStation("MicroStationDGN.DataBlock");
            DB.CopyString(ref projectName, true);
            Ae = myApp.CreateApplicationElement(DbID, DB);
            myApp.ActiveModelReference.AddElement((BIM.Element)Ae);
        }
        //删除DataBlock
        public static void DeleteAppBlock(int DbID)
        {
            BIM.Application myApp = BMI.Utilities.ComApp;
            DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
            BIM.ElementEnumerator eE = myApp.ActiveModelReference.Scan();
            while (eE.MoveNext())
            {
                if (BIM.MsdElementType.MicroStation == eE.Current.Type && eE.Current.Subtype == BIM.MsdElementSubtype.ApplicationElement)
                {
                    BIM.ApplicationElement Ae = (BIM.ApplicationElement)eE.Current;
                    if (Ae.ApplicationID == DbID)
                    {
                        BIM.DataBlock DB = Ae.GetApplicationData();

                        myApp.ActiveModelReference.RemoveElement((BIM.Element)Ae);
                    }
                }
            }
            
        }

        public static void DeleteAppBlock(int DbID, BIM.ElementEnumerator eE)
        {
            BIM.Application myApp = BMI.Utilities.ComApp;
            //DgnModel dgnModel = Session.Instance.GetActiveDgnModel();

            //BIM.ElementEnumerator eE = myApp.ActiveModelReference.Scan();
            while (eE.MoveNext())
            {
                if (BIM.MsdElementType.MicroStation == eE.Current.Type && eE.Current.Subtype == BIM.MsdElementSubtype.ApplicationElement)
                {
                    BIM.ApplicationElement Ae = (BIM.ApplicationElement)eE.Current;
                    if (Ae.ApplicationID == DbID)
                    {
                        BIM.DataBlock DB = Ae.GetApplicationData();

                        myApp.ActiveModelReference.RemoveElement((BIM.Element)Ae);
                    }
                }
            }
        }


        public static string GetProjectName(int DbID)
        {
            string Pname = "";
            BIM.Application myApp = BMI.Utilities.ComApp;
            DgnModel dgnModel = Session.Instance.GetActiveDgnModel();

            BIM.ElementEnumerator eE = myApp.ActiveModelReference.Scan();
            while (eE.MoveNext())
            {
                if (BIM.MsdElementType.MicroStation == eE.Current.Type && eE.Current.Subtype == BIM.MsdElementSubtype.ApplicationElement)
                {
                    BIM.ApplicationElement Ae = (BIM.ApplicationElement)eE.Current;
                    if (Ae != null)
                    {
                        if (Ae.ApplicationID == DbID)
                        {
                            BIM.DataBlock DB = Ae.GetApplicationData();
                            DB.CopyString(ref Pname, false);
                        }
                    }
                }
            }
            return Pname;
        }

        /// <summary>
        /// 打开当前文件,获取某条路线的DataBlock数据
        /// </summary>
        /// <param name="DbID">DataBlock标识ID</param>
        /// <returns></returns>
        public static string GetProjectName(int DbID, BIM.ElementEnumerator eE)
        {
            string Pname = "";
            //BIM.Application myApp = BMI.Utilities.ComApp;
            //DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
            try
            {
                string txt = null;
                while (eE.MoveNext())
                {
                    txt += eE.Current.Type.ToString() + "\r\n";

                    if (BIM.MsdElementType.MicroStation == eE.Current.Type && eE.Current.Subtype == BIM.MsdElementSubtype.ApplicationElement)
                    {
                        string type = eE.Current.Type.ToString() + " " + eE.Current.Subtype.ToString();

                        BIM.ApplicationElement Ae =/* (BIM.ApplicationElement)eE.Current; */eE.Current as BIM.ApplicationElement;
                        if (Ae.ApplicationID == DbID)
                        {
                            BIM.DataBlock DB = Ae.GetApplicationData();
                            DB.CopyString(ref Pname, false);
                            //此处不能退出, 要找到最后一个,才是正确的
                            //break;
                        }
                    }
                }
            }
            catch (Exception)
            {
                eE.Reset();
                return Pname;
            }

            eE.Reset();
            return Pname;
        }

        /// <summary>
        /// 内存中打开指定文件和模型,获取某条路线的DataBlock数据
        /// </summary>
        /// <param name="DbID">DataBlock标识ID</param>
        /// <param name="FullFile">DGN全路径</param>
        /// <param name="ModelName">模型名</param>
        /// <returns></returns>
        public static string GetProjectName(int DbID, string FullFile, string ModelName)
        {
            string Pname = "";
            BIM.Application myApp = BMI.Utilities.ComApp;
            BIM.DesignFile dgnFile = myApp.OpenDesignFileForProgram(FullFile, true);
            List<string> listStr = new List<string>();
            BIM.ElementEnumerator eE = dgnFile.Models[ModelName].Scan();
            while (eE.MoveNext())
            {
                if (BIM.MsdElementType.MicroStation == eE.Current.Type && eE.Current.Subtype == BIM.MsdElementSubtype.ApplicationElement)
                {
                    BIM.ApplicationElement Ae = (BIM.ApplicationElement)eE.Current;

                    if (Ae.ApplicationID == DbID)
                    {
                        BIM.DataBlock DB = Ae.GetApplicationData();
                        DB.CopyString(ref Pname, false);
                        break;
                    }
                    //else if(Ae.ApplicationID ==1)
                    //{
                    //    BIM.DataBlock DB = Ae.GetApplicationData();
                    //    DB.CopyString(ref Pname, false);
                    //    break;
                    //}
                    //获取所有DB索引值
                    listStr.Add(Ae.ApplicationID.ToString());
                }
            }

            dgnFile.Close();

            return Pname;
        }





        //将属性赋值给元素, 参数: 元素ID, 库名, 组名, 属性显示名, 属性类型, 属性值
        public static void AttachItem(ElementId elemId,string itemLibName, string itemTypeName, string propertyName,  TypeKind propertyType, object propertyValue)
        {
            DgnFile dgnFile = Session.Instance.GetActiveDgnFile();
            DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
            Element elem = dgnModel.FindElementById(elemId);
            CustomItemHost host = new CustomItemHost(elem, true);
           
            ItemTypeLibrary itemTypeLibrary = ItemTypeLibrary.FindByName(itemLibName, dgnFile);
            if (null == itemTypeLibrary)
            {
                itemTypeLibrary = ItemTypeLibrary.Create(itemLibName, dgnFile);
            }
            ItemType itemType = itemTypeLibrary.GetItemTypeByName(itemTypeName);
            if (itemType==null)
            {
                itemType = itemTypeLibrary.AddItemType(itemTypeName);
				itemTypeLibrary.Write();
            }
            IDgnECInstance item = host.GetCustomItem(itemLibName, itemTypeName);
            if (item == null)
            {
                item = host.ApplyCustomItem(itemType, true);
            }
            CustomProperty property = itemType.GetPropertyByName(propertyName);
            if (property==null)
            {
                CustomProperty Cp = itemType.AddProperty(propertyName);
                Cp.Type = propertyType;
                switch (Cp.Type)
                {
                    case TypeKind.Boolean:
                        Cp.DefaultValue = (bool)propertyValue;
                        break;
                    case TypeKind.String:
                        Cp.DefaultValue = (string)propertyValue;
                        break;
                    case TypeKind.DateTime:
                        Cp.DefaultValue = (DateTime)propertyValue;
                        break;
                    case TypeKind.Double:
                        Cp.DefaultValue = (double)propertyValue;
                        break;
                    case TypeKind.Integer:
                        Cp.DefaultValue = (int)propertyValue;
                        break;
                    case TypeKind.Point:
                        Cp.DefaultValue = (DPoint3d)propertyValue;
                        break;
                }
            }
            else
            {
                string internalName = property.InternalName;
                IECPropertyValue val = item.GetPropertyValue(internalName);
                
                switch (propertyType)
                {
                    case TypeKind.Boolean:
                        item.SetValue(internalName,(bool)propertyValue);
                        break;
                    case TypeKind.String:
                        item.SetValue(internalName, (string)propertyValue);
                        break;
                    case TypeKind.DateTime:
                        item.SetValue(internalName, (DateTime)propertyValue);
                        break;
                    case TypeKind.Double:
                        item.SetValue(internalName, (double)propertyValue);
                        break;
                    case TypeKind.Integer:
                        item.SetValue(internalName, (int)propertyValue);
                        break;
                    case TypeKind.Point:
                        item.SetValue(internalName, (DPoint3d)propertyValue);
                        break;
                }
            }
             itemTypeLibrary.Write();
 
            item.ScheduleChanges(elem);
            elem.ReplaceInModel(elem);
        }

        //将属性赋值给元素, 参数: 元素ID, 库名, 组名, 属性显示名, 属性类型, 属性值 
        public static void AttachItemToAlignment(Element elem, string itemLibName, string itemTypeName, string propertyName, TypeKind propertyType, object propertyValue)
        {
            try
            {
                DgnFile dgnFile = Session.Instance.GetActiveDgnFile();
                DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
                CustomItemHost host = new CustomItemHost(elem, true);

                ItemTypeLibrary itemTypeLibrary = ItemTypeLibrary.FindByName(itemLibName, dgnFile);
                if (null == itemTypeLibrary)
                {
                    itemTypeLibrary = ItemTypeLibrary.Create(itemLibName, dgnFile);
                }
                ItemType itemType = itemTypeLibrary.GetItemTypeByName(itemTypeName);
                if (itemType == null)
                {
                    itemType = itemTypeLibrary.AddItemType(itemTypeName);
                    itemTypeLibrary.Write();
                }
                itemTypeLibrary.Write();
                IDgnECInstance item = host.GetCustomItem(itemLibName, itemTypeName);
                if (item == null)
                {
                    item = host.ApplyCustomItem(itemType, true);
                }
                CustomProperty property = itemType.GetPropertyByName(propertyName);
                if (property == null)
                {
                    CustomProperty Cp = itemType.AddProperty(propertyName);
                    Cp.Type = propertyType;
                    itemTypeLibrary.Write();
                    switch (Cp.Type)
                    {
                        case TypeKind.Boolean:
                            Cp.DefaultValue = (bool)propertyValue;
                            break;
                        case TypeKind.String:
                            Cp.DefaultValue = (string)propertyValue;
                            break;
                        case TypeKind.DateTime:
                            Cp.DefaultValue = (DateTime)propertyValue;
                            break;
                        case TypeKind.Double:
                            Cp.DefaultValue = (double)propertyValue;
                            break;
                        case TypeKind.Integer:
                            Cp.DefaultValue = (int)propertyValue;
                            break;
                        case TypeKind.Point:
                            Cp.DefaultValue = (DPoint3d)propertyValue;
                            break;
                    }
                }
                else
                {
                    string internalName = property.InternalName;
                    IECPropertyValue val = item.GetPropertyValue(internalName);

                    switch (propertyType)
                    {
                        case TypeKind.Boolean:
                            item.SetValue(internalName, (bool)propertyValue);
                            break;
                        case TypeKind.String:
                            item.SetValue(internalName, (string)propertyValue);
                            break;
                        case TypeKind.DateTime:
                            item.SetValue(internalName, (DateTime)propertyValue);
                            break;
                        case TypeKind.Double:
                            item.SetValue(internalName, (double)propertyValue);
                            break;
                        case TypeKind.Integer:
                            item.SetValue(internalName, (int)propertyValue);
                            break;
                        case TypeKind.Point:
                            item.SetValue(internalName, (DPoint3d)propertyValue);
                            break;
                    }
                }
                itemTypeLibrary.Write();

                item.ScheduleChanges(elem);
                elem.ReplaceInModel(elem);
            }
            catch (Exception)
            {
                return;
            }
        }

        /// <summary>
        /// 从元素中读取EC属性，不依赖于EC ItemTypeLibrary，可读取参考文件EC
        /// </summary>
        /// <param name="elem">元素</param>
        /// <param name="propertyName">属性名</param>
        /// <returns></returns>
        public static string GetElePropertyValue(Element elem, string propertyName)
        {
            CustomItemHost host = new CustomItemHost(elem, true);
            //ECNameValidation.EncodeToValidName(ref propertyName);  //将字符串转成编码格式  (存在问题："__x8bbe____x8ba1____x65f6____x901f____x0028__km__x002f__h__x0029__"  正确的应为:"__x8BBE____x8BA1____x65F6____x901F____x0028__km__x002F__h__x0029__")
            //ECNameValidation.DecodeFromValidName(ref propertyName);  //将编码转为字符串 （不存在问题）
            IList<IDgnECInstance> ECList = host.CustomItems;
            foreach (IDgnECInstance item in ECList)
            {
                IEnumerator<IECPropertyValue> propertis = item.GetEnumerator(true);
                while (propertis.MoveNext())
                {
                    string accessString = propertis.Current.AccessString;
                    ECNameValidation.DecodeFromValidName(ref accessString);
                    if (accessString == propertyName)
                    {
                        return propertis.Current.StringValue;
                    }
                }
            }
            return "";
        }
        public static void DetachItem(string itemLibName, string itemTypeName, ElementId elemId)
        {
            DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
            Element elem = dgnModel.FindElementById(elemId);
            Element newElem = elem;
            CustomItemHost host = new CustomItemHost(newElem, true);
            IDgnECInstance item = host.GetCustomItem(itemLibName, itemTypeName);

            item.ScheduleDelete(newElem);
            newElem.ReplaceInModel(elem);
        }
        //从元素中读取某属性显示名的属性值(返回string), 参数: 元素ID, 库名, 组名, 属性显示名 
        //string StrHxd = "例子";
        //bool HXD = Bentley.ECObjects.ECObjects.StringToBoolean(StrHxd); 
        public static string getElePropertyValue(Element elem, string itemLibName, string itemTypeName, string propertyName) //ElementId elemId
        {
            string tempDic = "";
            DgnFile dgnFile = Session.Instance.GetActiveDgnFile();
            DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
            //Element elem = dgnModel.FindElementById(elemId);
            CustomItemHost host = new CustomItemHost(elem, true);

            ItemTypeLibrary itemTypeLibrary = ItemTypeLibrary.FindByName(itemLibName, dgnFile);
            if (null == itemTypeLibrary)
            {
                return tempDic;
            }
            ItemType itemType = itemTypeLibrary.GetItemTypeByName(itemTypeName);
            if (itemType == null)
            {
                return tempDic;
            }
            IDgnECInstance item = host.GetCustomItem(itemLibName, itemTypeName);
            if (item == null)
            {
                return tempDic;
            }
            CustomProperty property = itemType.GetPropertyByName(propertyName);
            string internalName = property.InternalName;
            IECPropertyValue val = item.GetPropertyValue(internalName);
            return val.StringValue;
         }

        //获取某元素的所有属性信息 参数: 元素ID的string格式
        public static void GetProperties(string elementID)
        {
            ulong id;
            try
            {
                id = ulong.Parse(elementID);
            }
            catch
            {
                MessageBox.Show("未提供ElemId作为命令参数或提供的参数不合法");
                return;
            }
            DgnFile dgnFile = Session.Instance.GetActiveDgnFile();
            DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
            Element myElem = dgnModel.FindElementById((ElementId)id);
            if (null == myElem)
            {
                MessageBox.Show("所提供ElemId无效");
                return;
            }
            //获取当前文件路径
            //Bentley.Interop.MicroStationDGN.Application msApp = Bentley.MstnPlatformNET.InteropServices.Utilities.ComApp;
            //string Path = msApp.ActiveDesignFile.FullName; //.path 文件路径
            System.IO.TextWriter tw = new System.IO.StreamWriter(Session.Instance.GetActiveFileName() +"-" + elementID + "-propertis.txt", false);

            DgnECManager ecManager = DgnECManager.Manager;
            int count = 0;
            DgnECInstanceCollection instCol = ecManager.GetElementProperties(myElem, ECQueryProcessFlags.SearchAllClasses);
            foreach (IDgnECInstance inst in instCol)
            {

                count++;
                tw.WriteLine("当前条目," + inst.ClassDefinition.DisplayLabel );  //+ "-" + inst.ClassDefinition.Name
                IEnumerator <IECProperty> propertyEnum = inst.ClassDefinition.GetEnumerator();
                while (propertyEnum.MoveNext())
                {
                    IECPropertyValue propertyValue = inst.GetPropertyValue(propertyEnum.Current.Name);
                    if (propertyValue.IsArray)
                    {
                        IECArrayValue arrayVal = propertyValue as IECArrayValue;
                        if (arrayVal.Count >= 1)
                            propertyValue = arrayVal[0];
                    }
                    string strVal;
                    double dblVal;
                    int intVal;
                    if (propertyValue.TryGetStringValue(out strVal))
                            tw.WriteLine(propertyEnum.Current.DisplayLabel +"," + strVal);   //propertyEnum.Current.Name 是dgn真正识别的属性名
                    else if (propertyValue.TryGetDoubleValue(out dblVal))
                            tw.WriteLine(propertyEnum.Current.DisplayLabel + "," + dblVal.ToString());
                    else if (propertyValue.TryGetIntValue(out intVal))
                        tw.WriteLine(propertyEnum.Current.DisplayLabel + "," + intVal.ToString());
                }
            }
            tw.Close();
        }


        //获取某元素的所有属性信息 参数: 元素ID的string格式
        public static void deleteProperties(string elementID,string Name条目)
        {
            ulong id;
            try
            {
                id = ulong.Parse(elementID);
            }
            catch
            {
                MessageBox.Show("未提供ElemId作为命令参数或提供的参数不合法");
                return;
            }
            DgnFile dgnFile = Session.Instance.GetActiveDgnFile();
            DgnModel dgnModel = Session.Instance.GetActiveDgnModel();
            Element myElem = dgnModel.FindElementById((ElementId)id);
            if (null == myElem)
            {
                MessageBox.Show("所提供ElemId无效");
                return;
            }
            //获取当前文件路径
            //Bentley.Interop.MicroStationDGN.Application msApp = Bentley.MstnPlatformNET.InteropServices.Utilities.ComApp;
            //string Path = msApp.ActiveDesignFile.FullName; //.path 文件路径
            //System.IO.TextWriter tw = new System.IO.StreamWriter(Session.Instance.GetActiveFileName() + "-" + elementID + "-propertis.txt", false);

            DgnECManager ecManager = DgnECManager.Manager;
            //int count = 0;
            DgnECInstanceCollection instCol = ecManager.GetElementProperties(myElem, ECQueryProcessFlags.SearchAllClasses);
            foreach (IDgnECInstance inst in instCol)
            {
                if (inst.ClassDefinition.DisplayLabel.Contains(Name条目))
                {
                    inst.Delete();
                }
                /*

                count++;
                tw.WriteLine("当前条目," + inst.ClassDefinition.DisplayLabel);  //+ "-" + inst.ClassDefinition.Name
                IEnumerator<IECProperty> propertyEnum = inst.ClassDefinition.GetEnumerator();
                while (propertyEnum.MoveNext())
                {
                    IECPropertyValue propertyValue = inst.GetPropertyValue(propertyEnum.Current.Name);
                    if (propertyValue.IsArray)
                    {
                        IECArrayValue arrayVal = propertyValue as IECArrayValue;
                        if (arrayVal.Count >= 1)
                            propertyValue = arrayVal[0];
                    }
                    string strVal;
                    double dblVal;
                    int intVal;
                    if (propertyValue.TryGetStringValue(out strVal))
                        tw.WriteLine(propertyEnum.Current.DisplayLabel + "," + strVal);   //propertyEnum.Current.Name 是dgn真正识别的属性名
                    else if (propertyValue.TryGetDoubleValue(out dblVal))
                        tw.WriteLine(propertyEnum.Current.DisplayLabel + "," + dblVal.ToString());
                    else if (propertyValue.TryGetIntValue(out intVal))
                        tw.WriteLine(propertyEnum.Current.DisplayLabel + "," + intVal.ToString());
                }
                */
            }
        }
    }
}